package com.travel.admin.util;

import java.nio.charset.StandardCharsets;
import java.security.Key;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import javax.xml.bind.DatatypeConverter;

import org.springframework.util.Base64Utils;

import com.travel.admin.constants.JsonWebToken;

import io.jsonwebtoken.Claims;
import io.jsonwebtoken.JwtBuilder;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;

public class EncryptUtil {
	private static final String DEFAULT_SECRET_KEY = "38659215534F141B5496BDF477D909A0";
	
	private static final String SECRET_KEY = DEFAULT_SECRET_KEY.substring(0,16);
	private static final String IV_PARAMETER = DEFAULT_SECRET_KEY.substring(16,32);
	
	private static final String TOKEN_USERID = "userId";
	private static final String TOKEN_USERNAME = "username";
	private static final String TOKEN_NAME = "name";
	private static final String TOKEN_TYPE = "type";
	
	public static String getRandPassword(){
        StringBuilder builder = new StringBuilder();
        List<Integer> list = NumberUtil.getRandomNumber(6);
        if(list != null){
        		for(Integer integer : list){
        			builder.append(integer);
        		}
        }
        return builder.toString();
	}
	
	public static String getCaptcha(){
        StringBuilder builder = new StringBuilder();
        List<Integer> list = NumberUtil.getRandomNumber(4);
        if(list != null){
        		for(Integer integer : list){
        			builder.append(integer);
        		}
        }
        return builder.toString();
	}
	public static String encodeWithAES(String str){
		if(!StringUtil.isEmpty(str)){
			try{
				IvParameterSpec ivParameterSpec = new IvParameterSpec(IV_PARAMETER.getBytes(StandardCharsets.UTF_8));
				SecretKeySpec secretKeySpec = new SecretKeySpec(SECRET_KEY.getBytes(StandardCharsets.UTF_8), "AES");
				Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5PADDING");
				cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec, ivParameterSpec);
				byte[] encrypted = cipher.doFinal(str.getBytes());
				return Base64Utils.encodeToString(encrypted);
			}catch (Exception e) {
				throw new RuntimeException(e);
			}
		}
		return null;
	}
	public static String decodeWithAES(String str){
		if(!StringUtil.isEmpty(str)){
			try{
				IvParameterSpec ivParameterSpec = new IvParameterSpec(IV_PARAMETER.getBytes(StandardCharsets.UTF_8));
				SecretKeySpec secretKeySpec = new SecretKeySpec(SECRET_KEY.getBytes(StandardCharsets.UTF_8), "AES");
				Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5PADDING");
				cipher.init(Cipher.DECRYPT_MODE, secretKeySpec, ivParameterSpec);
				byte[] decrypted = cipher.doFinal(Base64Utils.decodeFromString(str));
				return new String(decrypted);
			}catch (Exception e) {
				throw new RuntimeException(e);
			}
		}
		return null;
	}
	public static String createJwt(JsonWebToken jsonWebToken) {
	    SignatureAlgorithm signatureAlgorithm = SignatureAlgorithm.HS256;
	    byte[] keySecretBytes = DatatypeConverter.parseBase64Binary(DEFAULT_SECRET_KEY);
	    Key signingKey = new SecretKeySpec(keySecretBytes, signatureAlgorithm.getJcaName());
	    JwtBuilder builder = Jwts.builder().setId(jsonWebToken.getId())
	                                .setIssuedAt(jsonWebToken.getIssuedAt())
	                                .setSubject(jsonWebToken.getSubject())
	                                .setIssuer(jsonWebToken.getIssuer())
	                                .setClaims(getClaims(jsonWebToken))
	                                .signWith(signatureAlgorithm, signingKey);
	    if(jsonWebToken.getExpiration() != null){
	    		builder.setExpiration(jsonWebToken.getExpiration());
	    }
	    return builder.compact();
	}
	
	public static JsonWebToken parseJwt(String jwt) {
	    Claims claims = Jwts.parser()         
	       .setSigningKey(DatatypeConverter.parseBase64Binary(DEFAULT_SECRET_KEY))
	       .parseClaimsJws(jwt).getBody();
	    JsonWebToken jsonWebToken = new JsonWebToken();
	    jsonWebToken.setId(claims.getId());
	    jsonWebToken.setIssuer(claims.getIssuer());
	    jsonWebToken.setIssuedAt(claims.getIssuedAt());
	    jsonWebToken.setSubject(claims.getSubject());
	    jsonWebToken.setExpiration(claims.getExpiration());
	    jsonWebToken.setUserId(Long.parseLong(claims.get(TOKEN_USERID).toString()));
	    jsonWebToken.setUsername(claims.get(TOKEN_USERNAME).toString());
	    jsonWebToken.setType(claims.get(TOKEN_TYPE).toString());
	    jsonWebToken.setName(claims.get(TOKEN_NAME).toString());
	    return jsonWebToken;
	}
	private static Map<String, Object> getClaims(JsonWebToken jsonWebToken) {
		Map<String, Object> map = new HashMap<String, Object>();
		map.put(TOKEN_USERID, jsonWebToken.getUserId());
		map.put(TOKEN_USERNAME, jsonWebToken.getUsername());
		map.put(TOKEN_NAME, jsonWebToken.getName());
		map.put(TOKEN_TYPE, jsonWebToken.getType());
		return map;
	}
	public static void main(String[] args) {
		Date date = DateUtil.getServerTime();
		JsonWebToken jsonWebToken = new JsonWebToken();
		jsonWebToken.setId("zxwy");
		jsonWebToken.setIssuer("100000");
		jsonWebToken.setSubject("100000");
		jsonWebToken.setIssuedAt(date);
		jsonWebToken.setExpiration(DateUtil.add(date, 2, 120));
		System.out.println(createJwt(jsonWebToken));
	}
}
